import { changeGear, patrolingRemote } from '@/api/control'
import { Mode, useModeStore } from '@/business/mode'
import { useMusicStore } from '@/business/music'
import { useVoiceStore } from '@/business/voice'
import { useCarStore } from '@/stores/car'
import { ElMessage } from '@/stores/elMessage'
import { i18n } from '@/utils'
import { ref, watch } from 'vue'
import { BottomButtons, Gears, TopButtons, useConsoleButton } from './consoleButtons'
import { useDisperse } from './disperse'
import { useLight } from './light'
import { usePantilt } from './usePantilt'

// 手柄、方向盘相关逻辑
export const useController = () => {
  const carStore = useCarStore()
  const { onButtonDown: onBottomButtonDown } = useConsoleButton()
  const { onButtonDown: onTopButtonDown } = useConsoleButton()
  const { toggleFloodingLight, toggleAlarmLight } = useLight()
  const { toggleDisperse } = useDisperse()
  const { changeMusic } = useMusicStore()
  const mode = useModeStore()

  /**
   * 速度
   */
  const speed = ref(0)

  /**
   * 档位
   * true - 倒车
   * false - 前进
   */
  const gear = ref(false)

  /**
   * 方向
   */
  const direction = ref(0)

  /**
   * 获取摇杆的值
   */
  function getJoyStickValue(value1: number, value2: number) {
    // 十进制向左移动 8 位并进行逻辑与操作
    let result = (value1 << 8) | value2
    result = Math.round(((result - 2048) / 4095) * 2000)
    return result
  }

  let st: any = null
  let seq = 0

  /**
   * 提交数据
   */
  function submitData() {
    const data = { x: speed.value, y: direction.value, seq }

    patrolingRemote(carStore.currentCar, data).then(() => {
      seq++
      // 协议要求 seq 不能大于 254
      if (seq > 254) {
        seq = 0
      }
      // 按住按钮的情况
      if (speed.value !== 0 || direction.value !== 0) {
        st = setTimeout(submitData, 200)
      }
    })
  }

  watch([speed, direction], () => {
    if (mode.carMode === Mode.MANUAL) {
      clearTimeout(st)
      submitData()
    } else {
      return
    }
  })

  const { onClickPantilt, PantiltMode, pantiltX, pantiltY } = usePantilt()
  const { handleTalkBack } = useVoiceStore()

  /**
   * 底部按钮对应的操作
   */
  const BottomButtonActionMap = new Map<BottomButtons, (status: boolean) => void>([
    [BottomButtons.STOP, (status: boolean) => mode.toggleStopMode(status)],
    [BottomButtons.STRONG_LIGHT, (status: boolean) => toggleFloodingLight(status)],
    [BottomButtons.AMPLIFIER_OPEN, (status: boolean) => toggleDisperse(status)],
    [BottomButtons.AMPLIFIER_CLOSE, (status: boolean) => toggleAlarmLight(status)],
    [BottomButtons.VOICE, (status: boolean) => handleTalkBack(status)],
    [BottomButtons.AUTO, (status: boolean) => mode.toggleAutoMode(status)],
    [
      BottomButtons.PANTILT_RESET,
      (status: boolean) => status && onClickPantilt(PantiltMode.RECALL, 255)
    ]
  ])

  /**
   * 顶部按钮对应的操作
   */
  const TopButtonActionMap = new Map<TopButtons, (status: boolean) => void>([
    [
      TopButtons.GEAR,
      (status: boolean) => {
        gear.value = status
        changeGear({
          code: carStore.currentCar,
          gear: status ? Gears.REVERSE : Gears.FORWARD
        })
      }
    ],
    [TopButtons.AUDIO_1, (status: boolean) => changeMusic('0', status)],
    [TopButtons.AUDIO_2, (status: boolean) => changeMusic('1', status)],
    [TopButtons.AUDIO_3, (status: boolean) => changeMusic('2', status)],
    [TopButtons.AUDIO_4, (status: boolean) => changeMusic('3', status)]
  ])

  /**
   * 连接中控台
   */
  async function connectControlPan() {
    // 弹窗选择匹配设备
    const port = await navigator.serial.requestPort()
    let ref: number
    // 断开连接后
    port.ondisconnect = () => {
      port.close()
      cancelAnimationFrame(ref)
    }
    /**
     * 不要动
     * @link https://github.com/itldg/web-serial-debug.git
     */
    const serialOptions: SerialOptions = {
      baudRate: 115200,
      dataBits: 8,
      stopBits: 1,
      parity: 'none',
      bufferSize: 1024,
      flowControl: 'none'
    }
    try {
      // 等待连接成功
      await port.open(serialOptions)
      ElMessage({
        type: 'success',
        message: i18n.global.t('lian-jie-cheng-gong')
      })
      // 设置为手动模式
      mode.setMode(Mode.MANUAL)
      /**
       * 获取数据
       */
      const onPort = async () => {
        if (port.readable) {
          const reader = port.readable.getReader()
          try {
            const { value, done } = await reader.read()
            if (!done) {
              if (value.length === 19) {
                // console.clear()
                // console.log(value)
                // 只有按住油门摇杆上方红色才能修改速度
                if (value[15] === 32) {
                  // 获取油门摇杆的值
                  speed.value = getJoyStickValue(value[12], value[13])
                } else {
                  // 松开油门摇杆上方红色按钮, 速度归零
                  speed.value = 0
                }
                // 获取方向摇杆的值
                direction.value = getJoyStickValue(value[2], value[3])
                // 获取底部按钮的值
                onBottomButton(value[16])
                // 获取顶部按钮的值
                onTopButton(value[17])
                // 获取云台摇杆的值
                pantiltX.value = (value[6] << 8) | value[7]
                pantiltY.value = (value[8] << 8) | value[9]
              }
            }
          } finally {
            reader.releaseLock()
          }
        }
        // 实时获取数据
        ref = requestAnimationFrame(onPort)
      }
      onPort()
    } catch {
      ElMessage({ type: 'error', message: i18n.global.t('jian-ce-dao-yi-lian-jie') })
    }
  }

  /**
   * 监听底部按钮并执行对应操作
   */
  const onBottomButton = (value: number) => {
    const bottomButton = onBottomButtonDown(value)
    if (bottomButton) {
      const actionGetter = BottomButtonActionMap.get(bottomButton.index)
      actionGetter && actionGetter(bottomButton.buttonStatus)
    }
  }

  /**
   * 监听顶部按钮并执行对应操作
   */
  const onTopButton = (value: number) => {
    const pressedButton = onTopButtonDown(value)
    if (pressedButton) {
      const actionGetter = TopButtonActionMap.get(pressedButton.index)
      actionGetter && actionGetter(pressedButton.buttonStatus)
    }
  }

  return {
    /**
     * 速度
     */
    speed,
    /**
     * 档位
     */
    gear,
    /**
     * 方向
     */
    direction,
    /**
     * 连接中控台
     */
    connectControlPan
  }
}
